home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 43 / Mac Magazin and MacEasy Magazine CD - Issue 43.iso / Software / Mobiles Büro / Newton / Newton Entwickler / DIL 2.0 Sample Code ƒ / SoupDrink-Mac-4 / SoupDrink.c < prev    next >
Text File  |  1997-04-17  |  21KB  |  697 lines

  1. /*    
  2.  *    File:        SoupDrink.c
  3.  * 
  4.  *    Contains:    Demonstration of the Newton Desktop Integration Libraries (DILs)
  5.  *              Communication DILs (CDILs) and High Level Frames DILs (FDILs)
  6.  *
  7.  *              This is the MacOS version of SoupDrink.
  8.  *              For the Windows code, see the file "SOUPDRNK.C".
  9.  *
  10.  *              Nearly all of the DIL code can be found in the file "engine.c".
  11.  *              The only interesting DIL code in here can be found near the 
  12.  *              top - in SetupPortMenu and InitializePipe
  13.  * 
  14.  *    Written by:    Rob Langhorne, J. Christopher Bell, and David Fedor
  15.  * 
  16.  *    Copyright:    © 1995-1997 by Apple Computer, Inc.  All rights reserved.
  17.  *
  18.  *  Disclaimer: This is nearly all MacOS-specific code.  It is not intended
  19.  *              to be an example of good MacOS sample code :-)  but it works to
  20.  *              demonstrate & test how the Newton DILs work.
  21.  *
  22.  */ 
  23.  
  24. #include <Types.h>
  25. #include <memory.h>
  26. #include <Packages.h>
  27. #include <Errors.h>
  28. #include <quickdraw.h>
  29. #include <fonts.h>
  30. #include <dialogs.h>
  31. #include <windows.h>
  32. #include <menus.h>
  33. #include <devices.h>
  34. #include <events.h>
  35. #include <diskinit.h>
  36. #include <OSUtils.h>
  37. #include <resources.h>
  38. #include <toolutils.h>
  39. #include <AppleEvents.h>
  40. #include <Strings.h>
  41. #include <stdio.h>
  42.  
  43. #define forMac  // this is a Macintosh-only source file...
  44. #include "DILCPipe.h"
  45. #include "HLFDIL.h"
  46. #include "AppDialogs.h"
  47. #include "SoupDrink.h"
  48. #include "Engine.h"
  49.  
  50.  
  51.  
  52. /******    Function prototypes  *******/
  53. void             EventLoop(void) ;
  54. Boolean            DoMenuItem(long val) ;
  55. void             DoDiskEvents(long dinfo) ;
  56. void             DoDeskAccCall(MenuHandle themenu, long theit) ;
  57. void             DisableExpertFuncs(void);
  58. void             EnableExpertFuncs(void);
  59.  
  60.  
  61. /********    Global variables **********/
  62.  
  63. // UI stuff
  64. MenuHandle        gAppleMenuHandle, gFileMenuHandle, gEditMenuHandle, gTestHandle, gPortHandle, gFuncMenuHandle;
  65. Boolean         gQuit;                    // Flags for application state
  66. int                gNumPorts;                // how many ports are in our port menu
  67.  
  68. // Configuration options set through menus
  69. long            gWhichPort,                // the number in the menu of which port to use
  70.                 gWhichTool;                // Selector for which communications tool to use
  71. Boolean         gEncrypt = false,        // Toggles for advanced reading and writing
  72.                 gByteSwap = false,
  73.                 gUseUnicode = false,
  74.                 gExpertMode = false;
  75.  
  76. // the following are globals set in here, used in Engine.c
  77. void            *ourPipe;
  78. void            *gThisObject;                /* This is the only DIL frame active at one time in this app */
  79. int                gInputMode;                    /* drink mode (receive frames) or spit mode (receive strings) */
  80. char            gReceivedString[kMAXSTR];     /* received string; used in 'spit mode' */
  81. long            gReceivedStringLen;            /* received string length (see above) */
  82. char             gTempBuffer [256];            /* a global string buffer for input dialogs, etc */
  83.  
  84.  
  85. // SetupPortMenu() demonstrates finding the available ports available on your machine.
  86. // Different model MacOS computers have different ports, and the port names can be 
  87. // localized into other languages.
  88. //
  89. // The port names are gotten from the Communications Toolbox and placed directly into
  90. // menu items.  Note that InitCRM() is not called - that is called by the DILs as part
  91. // of CDInitCDIL().  (Future versions of the DILs might not call it, though - watch
  92. // for more information on this.)
  93. //
  94. // SoupDrink has a "config" menu to which this function adds port names.  When it comes
  95. // time to call CDPipeInit, the port name is taken directly out of the menu.
  96. //
  97. // The basis for this routine was stolen from:
  98. // http://dev.info.apple.com/source/code/Snippets/Communications_Toolbox/FindSerialPorts/ReadMe.html
  99.  
  100. #include <CommResources.h>
  101. #include <CRMSerialDevices.h>
  102.  
  103. void SetupPortMenu()
  104. {
  105.     CRMRec            c;
  106.     CRMRecPtr        cPtr = &c;
  107.     CRMSerialPtr    serialPtr;
  108.         
  109.     gNumPorts = 0;
  110.     c.crmDeviceType = crmSerialDevice;
  111.     c.crmDeviceID   = 0;
  112.     while (cPtr != nil) {
  113.         cPtr = (CRMRecPtr)CRMSearch(&c);
  114.         if (cPtr) {
  115.             serialPtr = (CRMSerialPtr)cPtr->crmAttributes;
  116.             AppendMenu(gPortHandle, *(serialPtr->name));    // this is a Pascal-style string, which is what AppendMenu wants.
  117.             gNumPorts++;
  118.             c.crmDeviceID = cPtr->crmDeviceID;
  119.         }
  120.     }
  121.        gWhichPort = kFirstPortItem;                // default to the first port in the list
  122.        if (gNumPorts)
  123.            CheckItem(gPortHandle, gWhichPort, true);    // put a checkmark next to it.
  124. }
  125.  
  126.  
  127. /*
  128.  * InitializePipe
  129.  *
  130.  * Purpose: This function sets up port options for the CDIL function called CDPipeInit.
  131.  *
  132.  * Note that if you do not "dispose" of the connection, the port can be locked and you will
  133.  * get the "port busy" error which will make life difficult for both you and users. It would
  134.  * be best if the function which Initializes the pipe takes responsibility for disposing of
  135.  * of the pipe.
  136.  */
  137. OSErr InitializePipe () 
  138. {
  139.     OSErr    fErr;
  140.     char    Port[100];
  141.  
  142.     // Copy the text for the port right out of the menu item.
  143.     // It'll look like "Modem Port" but could be localized into another language!
  144.     getitem(gPortHandle, gWhichPort, Port);
  145.     
  146.     switch (gWhichTool) {
  147.         case kSerialTool:
  148.             fErr = CDPipeInit(ourPipe, "Serial","","Baud 38400 dataBits 8 Parity None Port ", Port, kDefaultBufferSize, kDefaultBufferSize);    
  149.             break;
  150.         case kModemTool:
  151.             fErr = CDPipeInit(ourPipe, "Modem","","ModemType \"Newton Serial Connection\" dataBits 8 Parity None Baud 38400 Port ", Port, kDefaultBufferSize, kDefaultBufferSize);    
  152.             break;
  153.         case kADSPTool:
  154.             fErr = CDPipeInit(ourPipe, "ADSP","My Desktop Mac","LocalADSPType \"SoupDrink\" RegisterName 1 LocalADSPName ", Port, kDefaultBufferSize, kDefaultBufferSize);    
  155.             break;
  156.         case kIRTool:
  157.             fErr = CDPipeInit(ourPipe, "IR","","", Port, kDefaultBufferSize, kDefaultBufferSize);    
  158.             break;
  159.         }
  160.     
  161.     return fErr;
  162. }
  163.  
  164. void ListenCallback( CommErr errorValue, long refCon )
  165. // This is only used by the "expert" mode, to test asynchronous listening...
  166. {
  167.     long length=5;
  168.     
  169.     if (errorValue)
  170.         PostAlertMessage("CDPipeAccept asynch returned:", ErrorStrings((int) errorValue, gTempBuffer), "", "");
  171.     else {
  172.         errorValue = CDPipeAccept(ourPipe) ;
  173.         if (errorValue)
  174.             PostAlertMessage("CDPipeAccept asynch returned:", ErrorStrings((int) errorValue, gTempBuffer), "", "");
  175.         else {
  176.             errorValue = CDPipeWrite(ourPipe, (void *)"asdf\4", &length, true,0,0,600,0,0);        // will generate an error on the Newton side
  177.             if (errorValue)
  178.                 PostAlertMessage("CDPipeWrite asynch returned:", ErrorStrings((int) errorValue, gTempBuffer), "", "");
  179.         }
  180.     }
  181. }
  182.  
  183.  
  184. /*
  185.  * encryptProc
  186.  *
  187.  * encryptProc is the encryption callback function
  188.  */
  189. static void encryptProc ( void *pData, Size Count, long refCon ) 
  190. {
  191.     Str255 refConStr;
  192.     char * localStr;
  193.     
  194.     
  195.     localStr = (char *) NewPtrClear(Count + 1);
  196.     if (!localStr)
  197.         return;
  198.         
  199.     strcpy(localStr, (char *)pData);
  200.     sprintf((char*) refConStr, "%d", refCon);
  201.     PostAlertMessage("We have encrypted:", (char*) localStr, " Reference constant: ", (char*) refConStr);
  202. }
  203.  
  204.  
  205. /*
  206.  * decryptProc
  207.  *
  208.  * decryptProc is the decryption callback function
  209.  */
  210. static void decryptProc ( void *pData, Size Count, long refCon ) 
  211. {
  212.     Str255 refConStr;
  213.     char * localStr;
  214.     
  215.     localStr = (char *)NewPtrClear(Count + 1);
  216.     if (!localStr)
  217.         return;
  218.  
  219.     strcpy(localStr,(char *) pData);
  220.     NumToString(Count, (unsigned char*) gTempBuffer);
  221.     sprintf((char*) refConStr, "%d", refCon);
  222.     PostAlertMessage("We have encrypted:", localStr, "Reference constant: ",(char*) refConStr);
  223. }
  224.  
  225.  
  226. /* StateStrings
  227.  * 
  228.  * Purpose: return state string based on state number from the CDILs
  229.  * (as a pascal string)
  230.  * note, if theErr is greater than 50, it is a user CDIL error
  231.  */
  232. char* StateStrings(int theState, Str255 theString)
  233. {
  234.     char* s;
  235.     char theNum[128];
  236.     
  237.     switch (theState) {
  238.         case kCDIL_Uninitialized:         s = "CDIL is uninitialized."; break;
  239.         case kCDIL_InvalidConnection:    s = "CDIL tried to bring up connection, but it failed."; break;
  240.         case kCDIL_Disconnected:          s = "CDIL is disconnected."; break;
  241.         case kCDIL_Listening:            s = "CDIL is listening for a connection."; break;
  242.         case kCDIL_ConnectPending:        s = "A CDIL connection is pending."; break;
  243.         case kCDIL_Connected:            s = "CDIL is connected."; break;
  244.         case kCDIL_Busy:                s = "CDIL is busy (either reading or writing)."; break;
  245.         case kCDIL_Aborting:            s = "CDIL is aborting."; break;
  246.         case kCDIL_Startup:                s = "CDIL is starting up."; break;
  247.         default:  s = (theState < 50) ? "Unknown CDIL state." : "(User-defined CDIL state)";
  248.         };
  249.         
  250.     strcpy((char*) theString, s);
  251.     strcat((char*) theString, ": State #");
  252.     NumToString(theState, (unsigned char*) theNum);
  253.     strcat((char*) theString,  (char*) p2cstr((unsigned char*)theNum));
  254.  
  255.     return (( char*) theString);
  256. }
  257.  
  258.  
  259. /*
  260.  *    Main
  261.  * 
  262.  *    This is the entry point for this application.
  263.  */
  264. void main(void)
  265. {
  266.     CommErr            fErr;
  267.      CursHandle         W;            /*    Cursor handle to get cursors    */
  268.     DialogPtr        splash;        /*    For use in splash screen */
  269.     Handle             MyMenu;                   /* my menu bar handle */
  270.     Cursor            myWatchCursor ;            /* The watch "busy" cursor */
  271.  
  272. #ifdef DEFINE_QD
  273. // This is needed for some compilers...
  274.     QDGlobals        qd;
  275. #endif
  276.  
  277.     /*     Start out with the standard Macintosh initializations */
  278.     MaxApplZone();
  279.     InitGraf((Ptr)&qd.thePort);
  280.     InitFonts();
  281.     InitWindows();
  282.     InitMenus();
  283.     TEInit();
  284.     InitDialogs(nil);
  285.     InitCursor();
  286.     MoreMasters();
  287.     MoreMasters();
  288.     MoreMasters();
  289.         
  290.      fErr = CDInitCDIL() ; 
  291.     if (fErr)  {
  292.         PostAlertMessage("Error initializing CDIL", ErrorStrings((int) fErr, gTempBuffer), "", "");
  293.         return;
  294.     }
  295.     
  296.     // Initialize the libraries themselves (does not make a connection)
  297.     fErr = FDInitFDIL();
  298.     if (fErr)  {
  299.         PostAlertMessage("Error initializing FDIL", ErrorStrings((int) fErr, gTempBuffer), "", "");
  300.         return;
  301.     }
  302.  
  303.     // Set up the menus
  304.     MyMenu = GetNewMBar(kMBarID);
  305.     SetMenuBar(MyMenu);
  306.     
  307.     gAppleMenuHandle = GetMenuHandle(kAppleMenu);
  308.     gFileMenuHandle = GetMenuHandle(kFileMenu);
  309.     gEditMenuHandle = GetMenuHandle(kEditMenu);
  310.     gTestHandle = GetMenuHandle(kTestMenu);
  311.     gPortHandle = GetMenuHandle(kPortMenu);
  312.     gFuncMenuHandle = GetMenuHandle(kFnMenu);
  313.     
  314.     // add desk accessories to the apple menu
  315.     AppendResMenu(gAppleMenuHandle, 'DRVR');
  316.         
  317.     SetupPortMenu();
  318.     if (gNumPorts==0){
  319.         PostAlertMessage("Error getting serial port names", "", "", "");
  320.         return;
  321.     }
  322.     
  323.     CheckItem(gPortHandle, kSerialTool, false);
  324.     CheckItem(gPortHandle, kModemTool, true);        // default to the modem tool
  325.     CheckItem(gPortHandle, kADSPTool, false);
  326.     CheckItem(gPortHandle, kIRTool, false);
  327.     gWhichTool = kModemTool;
  328.     
  329.     DisableExpertFuncs();
  330.  
  331.     DrawMenuBar();
  332.  
  333.     // Turn on the watch cursor while the splash screen is showing
  334.     W = GetCursor (watchCursor);
  335.     if (W)
  336.         myWatchCursor = **W;
  337.  
  338.       SetCursor((CursPtr)&myWatchCursor);
  339.       ShowCursor();
  340.     
  341.     ShowSplash(&splash);
  342.  
  343.     ourPipe = CDCreateCDILObject();
  344.     if (!ourPipe) {
  345.         PostAlertMessage("Error instantiating CDIL", "", "", "");
  346.         return;
  347.     }
  348.  
  349.     HideSplash(splash);
  350.     HideCursor();
  351.     SetCursor((const Cursor *)&qd.arrow);
  352.     ShowCursor();
  353.  
  354.     EventLoop ();
  355.  
  356.     fErr = CDPipeDisconnect (ourPipe);
  357.     
  358.     CDDisposeCDILObject( ourPipe ) ;
  359.     CDDisposeCDIL() ;
  360. #ifdef useASLM
  361.     CleanupLibraryManager();
  362. #endif
  363. }
  364.  
  365. /*
  366.  * EventLoop
  367.  *
  368.  * Purpose: This is the main Macintosh event loop processor.
  369.  *          This function must handle any type of Macintosh event
  370.  *          like mouse clicks and keyboard events.
  371.  */
  372. void EventLoop ( void )
  373. {
  374.     EventRecord     gERecord;                /* Current Macintosh Toolbox event record */
  375.     WindowPtr    twindow;
  376.     short        part;
  377.     
  378.      do {
  379.         CDIdle(ourPipe);
  380.         WaitNextEvent(everyEvent, &gERecord, 30, nil);
  381.         
  382.         switch (gERecord.what) {
  383.             case mouseDown:
  384.                 /* first see where the hit was */
  385.                 part = FindWindow(gERecord.where, &twindow);
  386.                 switch (part) {
  387.                     
  388.                     case inDesk:                            /* if they hit in desk, then the process manager */
  389.                         break;                              /* will switch us out, we don't need to do anything */
  390.  
  391.                     case inMenuBar:
  392.                         DoMenuItem(MenuSelect(gERecord.where));
  393.                         break;
  394.                         
  395.                     case inSysWindow:    /* pass to the system */
  396.                         SystemClick(&gERecord, twindow);
  397.                         break;
  398.                         
  399.                     case inContent:    /*    This app doesn't do windows    */
  400.                     case inDrag:
  401.                     case inGrow:
  402.                     case inGoAway:
  403.                     case inZoomIn:                            
  404.                     case inZoomOut:
  405.                         break;
  406.         
  407.                 }
  408.                 break;
  409.  
  410.             case keyUp:                /* don't care */
  411.             case mouseUp:            /* don't care */
  412.             case networkEvt:        /* don't care */
  413.             case driverEvt:            /* don't care */
  414.             case kHighLevelEvent:    /*    AppleEvents    */
  415.                 break;
  416.  
  417.             case keyDown:
  418.             case autoKey:
  419.                 if (gERecord.modifiers & cmdKey)
  420.                     DoMenuItem(MenuKey((short)(gERecord.message & charCodeMask)));
  421.                 else
  422.                     SysBeep(2);
  423.                 break;
  424.  
  425.             case diskEvt:
  426.                 /* We don't do anything special for disk events, this just passes them
  427.                  * to a function that checks for an error on the mount
  428.                  */
  429.                 DoDiskEvents((long)gERecord.message);
  430.                 break;
  431.  
  432.             default:
  433.                 break;
  434.                 
  435.         }
  436.     } while (gQuit != true);
  437. }
  438.  
  439. /*
  440.  * DoDeskAccCall
  441.  *
  442.  * DoDeskAccCall opens the requested DA
  443.  */
  444.  
  445. void DoDeskAccCall(MenuHandle themenu, long theit)
  446. {
  447.     Str255 DAname;
  448.     
  449.     GetMenuItemText(themenu, (short)theit, DAname);
  450.     OpenDeskAcc(DAname);
  451. }    /*    end DoDeskAccCall    */
  452.  
  453. /*
  454.  * DoDiskEvents
  455.  *
  456.  * DoDiskEvents performs disk mount operations
  457.  */
  458. void DoDiskEvents(long dinfo)    /* hi word is error code, lo word is drive number */
  459. {
  460.     short theHighWord, theLowWord, hdl;
  461.     Point mountpoint =  {
  462.         40, 40
  463.     };
  464.     
  465.     theHighWord = HiWord(dinfo);
  466.     theLowWord = LoWord(dinfo);
  467.     if (theHighWord != noErr)/* something happened */ {
  468.         hdl = DIBadMount(mountpoint, dinfo);
  469.     }
  470. }    
  471.  
  472. /*
  473.  * DoMenuItem
  474.  *
  475.  * DoMenuItem processes a menu event
  476.  */
  477.  
  478. Boolean DoMenuItem(long val)
  479. {
  480.     short                 theLowWord, theHighWord;
  481.     CommErr                fErr = 0;
  482.     Str255                stateString;
  483.     CDIL_State            state;
  484.  
  485.     theLowWord = LoWord(val);
  486.     theHighWord = HiWord(val);
  487.     
  488.     switch (theHighWord) {                                  /* switch off the menu number selected */
  489.         case kAppleMenu:                                    /* Apple menu */
  490.             if (theLowWord != 1)                             /* if this was not About, it's a DA */
  491.                 DoDeskAccCall(gAppleMenuHandle, theLowWord);
  492.             else 
  493.                 Alert(kAboutDialog, nil);                 /* do about box */
  494.             break;
  495.             
  496.         case kFileMenu:                                        /* File menu */
  497.             gQuit = true;                                    /* only edit item */
  498.             break;
  499.  
  500.         case kEditMenu:                                        /* don't care */
  501.             SysBeep(1);  /* in this release, we don't do anything */
  502.             break;
  503.  
  504.         case kTestMenu:                                        /*    Test suites    */
  505.             switch(theLowWord) {
  506.                 case kSoupDrinkItem:
  507.                     fErr = SoupDrink();
  508.                     if (fErr)
  509.                         PostAlertMessage("Error from Soup Drink", ErrorStrings((int) fErr, gTempBuffer), "", "");
  510.                     break;
  511.                 
  512.                 case kNewNameItem:                            /* Create a new Names Soup entry on the Newton */
  513.                     fErr = UploadNewName();
  514.                     if (fErr)
  515.                         PostAlertMessage("Error from UploadNewName", ErrorStrings((int) fErr, gTempBuffer), "", "");
  516.                     break;
  517.                         
  518.                 default:                                    /* Sanity check. Shouldn't get here */
  519.                     SysBeep(1);  /* in this release, we don't do anything */
  520.                     break;
  521.             }
  522.             break;
  523.             
  524.         case kPortMenu:    //    Choose a port…
  525.              switch(theLowWord) {
  526.                 case kSerialTool:
  527.                 case kModemTool:
  528.                 case kADSPTool:
  529.                 case kIRTool:
  530.                     CheckItem(gPortHandle, kSerialTool, (theLowWord==kSerialTool));
  531.                     CheckItem(gPortHandle, kModemTool, (theLowWord==kModemTool));
  532.                     CheckItem(gPortHandle, kADSPTool, (theLowWord==kADSPTool));
  533.                     CheckItem(gPortHandle, kIRTool, (theLowWord==kIRTool));
  534.                     gWhichTool = theLowWord;
  535.                     break;
  536.  
  537.                 default: {
  538.                     int i;
  539.                     
  540.                     for (i=0; i<gNumPorts; i++)
  541.                         CheckItem(gPortHandle, kFirstPortItem + i, (theLowWord== kFirstPortItem + i));
  542.                     gWhichPort = theLowWord;
  543.                     break;
  544.                 }
  545.             } 
  546.             break;
  547.             
  548.         case kFnMenu: // Choose a function …
  549.              switch(theLowWord) {
  550.                 case kFInitItem:
  551.                     fErr = InitializePipe();
  552.                     if (fErr)
  553.                         PostAlertMessage("InitializePipe returned:", ErrorStrings((int) fErr, gTempBuffer), "", "");
  554.                     break;
  555.                     
  556.                 case kFListenItem:
  557.                     fErr = CDPipeListen(ourPipe, kDefaultTimeout, (CDILCompletionProcPtr)ListenCallback, 0) ;
  558.                     if (fErr)
  559.                         PostAlertMessage("CDPipeListen returned:", ErrorStrings((int) fErr, gTempBuffer), "", "");
  560.                     break;
  561.                     
  562.                 case kFAcceptItem:
  563.                     fErr = CDPipeAccept(ourPipe) ;
  564.                     if (fErr)
  565.                         PostAlertMessage("CDPipeAccept returned:", ErrorStrings((int) fErr, gTempBuffer), "", "");
  566.                     break;
  567.                     
  568.                 case kFAbortItem:
  569.                     fErr = CDPipeAbort(ourPipe, kAllPipes) ;
  570.                     if (fErr)
  571.                         PostAlertMessage("CDPipeAbort returned:", ErrorStrings((int) fErr, gTempBuffer), "", "");
  572.                     break;
  573.                     
  574.                 case kFDiscItem:
  575.                     fErr = CDPipeDisconnect(ourPipe) ;
  576.                     if (fErr)
  577.                         PostAlertMessage("CDPipeDisconnect returned:", ErrorStrings((int) fErr, gTempBuffer), "", "");
  578.                     break;
  579.                     
  580.                 case kFReadItem:
  581.                     SysBeep(1);  /* in this release, we don't do anything */
  582.                     break;
  583.                     
  584.                 case kFCountItem:
  585.                     SysBeep(1);  /* in this release, we don't do anything */
  586.                     break;
  587.                     
  588.                 case kFWriteItem:
  589.                     SysBeep(1);  /* in this release, we don't do anything */
  590.                     break;
  591.                     
  592.                 case kFGetStateItem:
  593.                     state = CDGetPipeState(ourPipe);
  594.  
  595.                     PostAlertMessage("Current state:", StateStrings(state, stateString), "", "");
  596.                     break;
  597.                     
  598.                 case kFSetStateItem: /* Set State number (for example, kCDIL_Busy) */
  599.                     SysBeep(1);  /* in this release, we don't do anything */
  600.                     break;
  601.  
  602.                 case kToggleEncryption:
  603.                     if (gEncrypt) {
  604.                         CDEncryptFunction(ourPipe, (CDILEncryptionProcPtr) nil, 0 ) ;
  605.                         CDDecryptFunction(ourPipe, (CDILDecryptionProcPtr) nil, 0 ) ;
  606.                         gEncrypt = false ;
  607.                     }
  608.                     else {
  609.                         CDEncryptFunction(ourPipe, (CDILEncryptionProcPtr) encryptProc, 100 ) ;
  610.                         CDDecryptFunction(ourPipe,  (CDILDecryptionProcPtr) decryptProc, 100 ) ;
  611.                         gEncrypt = true ;
  612.                     }    
  613.                     CheckItem(gFuncMenuHandle, kToggleEncryption, gEncrypt);
  614.                     
  615.                     break;
  616.                     
  617.                 case kToggleByteSwap:
  618.                     if (gByteSwap)
  619.                         gByteSwap = false ;
  620.                     else
  621.                         gByteSwap = true ;
  622.                         
  623.                     CheckItem(gFuncMenuHandle, kToggleByteSwap, gByteSwap);
  624.                     break;
  625.                     
  626.                 case kToggleUnicode:
  627.                     if (gUseUnicode)
  628.                         gUseUnicode = false ;
  629.                     else
  630.                         gUseUnicode = true ;
  631.                         
  632.                     CheckItem(gFuncMenuHandle, kToggleUnicode, gUseUnicode);
  633.                     break;
  634.                 case kExpertModeToggle:
  635.                     if (gExpertMode) {
  636.                         gExpertMode = false ;
  637.                         DisableExpertFuncs();
  638.                         }
  639.                     else {
  640.                         gExpertMode = true ;
  641.                         EnableExpertFuncs();
  642.                         }
  643.                         
  644.                     CheckItem(gFuncMenuHandle, kExpertModeToggle, gExpertMode);
  645.                     break;
  646.  
  647.                 default:    
  648.                     SysBeep(1);  //    Sanity check; shouldn't get here
  649.                     break;
  650.             }
  651.             
  652.     }
  653.     HiliteMenu(0);                        // Unhilite the menu label itself
  654.     return noErr;
  655. }    /*    end DoMenuItem    */
  656.  
  657.  
  658. void EnableExpertFuncs(void) {
  659.     EnableItem(gFuncMenuHandle,kFInitItem);
  660.     EnableItem(gFuncMenuHandle,kFListenItem);
  661.     EnableItem(gFuncMenuHandle,kFAcceptItem);
  662.     EnableItem(gFuncMenuHandle,kFAbortItem);
  663.     EnableItem(gFuncMenuHandle,kFDiscItem);
  664.     // in this release, these items are not supported...
  665.     //EnableItem(gFuncMenuHandle,kFReadItem);
  666.     //EnableItem(gFuncMenuHandle,kFCountItem);
  667.     //EnableItem(gFuncMenuHandle,kFWriteItem);
  668.     //EnableItem(gFuncMenuHandle,kFSetStateItem);
  669.     EnableItem(gFuncMenuHandle,kToggleEncryption);
  670.     EnableItem(gFuncMenuHandle,kToggleByteSwap);
  671.     EnableItem(gFuncMenuHandle,kToggleUnicode);
  672. }
  673.  
  674. void DisableExpertFuncs(void) {
  675.     DisableItem(gFuncMenuHandle,kFInitItem);
  676.     DisableItem(gFuncMenuHandle,kFListenItem);
  677.     DisableItem(gFuncMenuHandle,kFAcceptItem);
  678.     DisableItem(gFuncMenuHandle,kFAbortItem);
  679.     DisableItem(gFuncMenuHandle,kFDiscItem);
  680.     DisableItem(gFuncMenuHandle,kFReadItem);
  681.     DisableItem(gFuncMenuHandle,kFCountItem);
  682.     DisableItem(gFuncMenuHandle,kFWriteItem);
  683.     DisableItem(gFuncMenuHandle,kFSetStateItem);
  684.     DisableItem(gFuncMenuHandle,kToggleEncryption);
  685.     DisableItem(gFuncMenuHandle,kToggleByteSwap);
  686.     DisableItem(gFuncMenuHandle,kToggleUnicode);
  687. }
  688.  
  689.  
  690. long CurrentTimeInSeconds()
  691. // return something indicating what time it is, in seconds units
  692. // This is only used to compare one time against another; it does
  693. // not need to have any relationship to the time of day.
  694. {
  695.     return (TickCount() / 60);
  696. }
  697.